<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

class PaypalPaymentController extends Controller
{

	public function accessRules()
	{
		return array(
			array('allow', // allow all users to perform 'index' and 'view' actions
				'actions' => array('index'),
				'users' => array('*'),
			),
			array('allow', // allow authenticated users to perform all actions
				'users' => array('@'),
			),
			array('deny',
				'users' => array('*'),
			),
		);
	}

	public function actionIndex()
	{
		$notify_email = Yii::app()->params['paypalEmail'];   //email address to which debug emails are sent to

		$req = 'cmd=_notify-validate';
		$textMail = "";

		foreach ($_POST as $key => $value) {
			$value = urlencode(stripslashes($value));
			$req .= "&$key=$value";
			$textMail .= $key . "   " . urldecode($value) . "\r\n";
		}


		$mailer = new Mailer();
		$mailer->layout = Yii::getPathOfAlias('common') . "/templates/emails/layouts/default.tpl";
		$mailer->addSender("tai.pohnean@smartvirtualoffice.com.sg", "TAI POH NEAN");
		$mailer->addRecipient("tai.pohnean@smartvirtualoffice.com.sg", "TAI POH NEAN");
		$mailer->addSubject("Payment for PROPSAGE");
		$tokenList = array();
		$tokenList["IPN"] = "result list " . $req;
		$mailer->createHTMLMail(Yii::getPathOfAlias('common') . "/templates/emails/paypal/paypal.tpl", $tokenList);
		$mailer->createHTMLMail(Yii::getPathOfAlias('common') . "/templates/emails/paypal/paypal.tpl", $tokenList);
		$mailer->sendMail();
//
		// post back to PayPal system to validate
		$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

		if (Yii::app()->params['paypalSandboxMode'] == true) {
			$fp = fsockopen('www.sandbox.paypal.com', 80, $errno, $errstr, 30);
		} else {
			$fp = fsockopen('www.paypal.com', 80, $errno, $errstr, 30);
		}

		$dataIPN = print_r($_POST, true);

		$this->logPaypalResponse("IPN POST: " . $dataIPN);

		//DB connect creds and email

		if (!$fp) {
			// HTTP ERROR
		} else {
			fputs($fp, $header . $req);
			while (!feof($fp)) {
				$res = fgets($fp, 1024);
			}

			// log the result
			$this->logPaypalResponse("RESPONSE FROM PAYPAL: " . $res);

			if (strcmp($res, "VERIFIED") == 0) {
				//Verify that this record is not already in paypal payments
				$psPaypalPayment = new PsPaypalPayment("new");

				$psPaypalPayment->attributes = $_POST;
				$psPaypalPayment->invoice_number = $_POST["invoice"];

				$psPaypalPaymentData = print_r($psPaypalPayment->attributes, true);
				$this->logPaypalResponse("New PsPayment: " . $psPaypalPaymentData);

				if ($psPaypalPayment->validate('invoice')) {
					// Find Invoice
					$criteria = new CDbCriteria;
					$criteria->condition = 'invoice_number=:invoice_number';
					$criteria->params = array(':invoice_number' => $psPaypalPayment->invoice_number);
					$psInvoice = PsInvoice::model()->find($criteria);

					$psPaypalPayment->ps_invoice_id = $psInvoice->id;

					if (!$psPaypalPayment->save()) {
						$this->logPaypalResponse("Error Saving paypal payment: " . print_r($psPaypalPayment->getErrors(), true));
					}

					if ($psInvoice == null) {
						$this->logPaypalResponse("Cannot find Invoice.");
						//This person paid you but there is no invoice , Send Admin Error
						if ($this->logProblemPayment("Invoice Number not in invoice table", $_POST["invoice"])) {
							//Send Admin Email Regarding this Transaction

							$tokens = array();
							$tokens["invoice_number"] = $_POST;
							$tokens["transaction_details"] = serialize($_POST);
						}
					} else {
						$invoiceObject = print_r($psInvoice, true);
						$this->logPaypalResponse("Found Invoice: " . $invoiceObject->attributes);

						//Determine if this invoice is already paid
						if ($psInvoice->paid == 0) { //0 = NOT PAID, 1 = paid, -1 = refunded
							$this->logPaypalResponse("Invoice not paid. Proceeding with saving of payment.");
							//Determine if the amount paid is the amount that he shoudl pay
							if ($psPaypalPayment->mc_gross == $psInvoice->amount) {
								try {
									$this->logPaypalResponse("Invoice matches paypal payment amount.");

									// Determine the agent for this
									$user = User::model()->findByPk($psInvoice->user_id);

									// Determine referrer, if any
									$referrer = $user->referrerUser;

									// If the referrer exists
									if ($referrer != null && !$user->hasCreditTransactions()) {
										$this->doReferralPurchaseBonus($user, $referrer);
									}

									// Load product
									$psProduct = PsProduct::model()->findByPk($_POST["item_number"]);

									$promoCode = strtoupper($user->custom_data["promo_code"]);
									$promoCodeToday = BuyCreditsForm::generatePromoCodeByDateString('today');
									$promoCodeYtd = BuyCreditsForm::generatePromoCodeByDateString('-1 day');

									$promoCodeIsValid = ($promoCode == $promoCodeToday || $promoCode == $promoCodeYtd);

									$transaction = Yii::app()->db->beginTransaction();
									try {
										// start - do promo code (signup bonus)
										if ($promoCodeIsValid) {
											$signupBonus = Yii::app()->params['signupBonus'];

											$this->logPaypalResponse("Promo Code: " . $user->custom_data["promo_code"]);

											// Give the agent signup bonus
											$user->addCredits($signupBonus, "Signup Bonus: " . $signupBonus . " (using Promo Code)", SYSTEM_NAME);
										} else {
											$this->logPaypalResponse("Promo_code not found");
										}
										// end - do promo code

										$this->logPaypalResponse("Credit Purchase: " . $psProduct->name . " \$" . $psProduct->credits_given . " @ \$" . $psInvoice->amount);

										if ($user->addCredits($psInvoice->credits, "Credit Purchase: " . $psProduct->name . " \$" . $psProduct->credits_given . " @ \$" . $psInvoice->amount, SYSTEM_NAME, $psInvoice->id)) {
											$user->updateCreditExpiry(Yii::app()->params["creditExpiryLimit"]);
											// do something
										} else {
											$errorMessage = print_r($user->getErrors(), true);
											$this->logPaypalResponse("Error adding credits: " . $errorMessage);
										}

										//change the expiry date of the credits
										$newValidDate = strtotime(date("Y-m-d") . "+" . $psProduct->valid_period_in_days . " day");
										$currentExpiryDate = strtotime($user->credit_expiry_date);

										if ($newValidDate > $currentExpiryDate) {
											$newValidDate = date("Y-m-d", $newValidDate);
											$user->credit_expiry_date = $newValidDate;
										}

										$psInvoice->paid = 1;
										if ($psInvoice->save()) {
											
										} else {
											$errorMessage = print_r($psInvoice->getErrors(), true);
											$this->logPaypalResponse("Error Saving Invoice: " . $errorMessage);
										}


										$transaction->commit();
									} catch (Exception $e) {
										$this->logPaypalResponse("Exception: " . $e->getTraceAsString());
										$transaction->rollback();
										throw $e;
									}
								} catch (Exception $e) {
									$errorMessage = $e->getMessage();
									$this->logPaypalResponse("Unexpected Error: " . $errorMessage);
								}
							} else if ($psPaypalPayment->mc_gross < $psInvoice->amount) {
								$this->logPaypalResponse("Invoice less than paypal payment amount.");

								//Under payment
								if ($this->logProblemPayment("Under Payment", $_POST["invoice"])) {
									//Send Admin Email Regarding this Transaction

									$tokens = array();
									$tokens["invoice_number"] = $_POST;
									$tokens["transaction_details"] = serialize($_POST);
								}
							} else if ($psPaypalPayment->mc_gross > $psInvoice->amount) {
								$this->logPaypalResponse("Invoice more than paypal payment amount.");

								//Over payment
								if ($this->logProblemPayment("Over Payment ( Customer Paid too much )", $_POST["invoice"])) {
									//Send Admin Email Regarding this Transaction

									$tokens = array();
									$tokens["invoice_number"] = $_POST;
									$tokens["transaction_details"] = serialize($_POST);
								}

								// Determine the agent for this
								$user = User::model()->findByPk($psInvoice->user_id);

								// Determine referrer, if any
								$referrer = $user->referrerUser;

								// If the referrer exists
								if ($referrer != null && !$user->hasCreditTransactions()) {
									$this->doReferralPurchaseBonus($user, $referrer);
								}

								$transaction = Yii::app()->db->beginTransaction();
								try {
									// start - do promo code (signup bonus)
									if ($user->custom_data["promo_code"] != '') {
										$signupBonus = Yii::app()->params['signupBonus'];

										// Give the agent signup bonus
										$user->addCredits($signupBonus, "Signup Bonus: " . $signupBonus . " (using Promo Code)", SYSTEM_NAME);
									}
									// end - do promo code

									if ($user->addCredits($psInvoice->credits, "Credit Purchase: " . $psProduct->name . " \$" . $psProduct->credits_given . " @ \$" . $psInvoice->amount, SYSTEM_NAME, $psInvoice->id)) {
										$user->updateCreditExpiry(Yii::app()->params["creditExpiryLimit"]);
										// do something
									} else {
										$errorMessage = print_r($user->getErrors(), true);
										$this->logPaypalResponse("Error adding credits: " . $errorMessage);
									}

									$psProduct = PsProduct::model()->findByPk($_POST["item_number"]);

									$newValidDate = strtotime(date("Y-m-d") . "+" . $psProduct->valid_period_in_days . " day");
									$currentExpiryDate = strtotime($user->credit_expiry_date);

									if ($newValidDate > $currentExpiryDate) {
										$newValidDate = date("Y-m-d", $newValidDate);
										$user->credit_expiry_date = $newValidDate;
									}
									$psInvoice->paid = 1;
									$psInvoice->save();



									$transaction->commit();
								} catch (Exception $e) {
									$transaction->rollback();
									$this->logPaypalResponse("Error transaction: " . $e->getMessage() . "\n" . $e->getTraceAsString());
								}
							}
						} else if ($psInvoice->paid == 1) {
							//paid already why is this showing again
						} else {
							//this transaction is reversed
						}
					}
				} else {
					$errorMessage = print_r($psPaypalPayment->getErrors(), true);
					$this->logPaypalResponse("Error Validating PsPaypalPayment: " . $errorMessage);
				}

				// Determine if the payment is complete. payment is in full
			} // NOT VERIFIED BY PAYPAL
			else {
				//This is a fake transaction
				if ($this->logProblemPayment("Fake Transaction - Paypal does not recognize this transaction and someone is injecting transactions", $_POST["invoice"])) {
					//Send Admin Email Regarding this Transaction

					$tokens = array();
					$tokens["invoice_number"] = $_POST;
					$tokens["transaction_details"] = serialize($_POST);
				}

				throw new PsPageNotFoundException();
				//print($res);
			}
		}
	}

	private function logPaypalResponse($string)
	{
		$timestamp = date(DATE_ISO8601, time());

		$stringData = "";
		if ($lineBreakBefore) {
			$stringData .= "\n";
		}
		$stringData .= "[" . $timestamp . "]" . $string . "\n";

		Yii::log($stringData, CLogger::LEVEL_INFO, 'paypal');

//		if (YII_DEBUG) {
//        $logfile = Yii::getPathOfAlias('application') . "/../logs/paypal.log";
//        $fh = fopen($logfile, 'a');
//        fwrite($fh, $stringData);
//        fclose($fh);
		$mailer = new Mailer;
		$mailer->Subject = 'DEBUG PAYPAL';
		$mailer->From = 'noreply@propsage.com';
		$mailer->FromName = 'PROPSAGE DEBUG';
		$mailer->AddAddress('tai.pohnean@smartvirtualoffice.com.sg', 'tai.pohnean@smartvirtualoffice.com.sg'); // Agency
		$mailer->Body = $string;

		$mailer->sendMail();
//		}
	}

	protected function doReferralPurchaseBonus($user, $referrer)
	{
		$referralBonus = Yii::app()->systemConfig->get('ReferralPurchaseBonus');

		$transaction = Yii::app()->db->beginTransaction();
		try {
			// Give the referree 10 extra credits
			$user->addCredits($referralBonus, "Referral Bonus: " . $referralBonus . " (Referrer: " . $referrer->name . ")", SYSTEM_NAME);

			// Give the referrer 10 extra credits
			$referrer->addCredits($referralBonus, "Referral Purchase Bonus: " . $referralBonus . " (For referring: " . $user->name . ")", SYSTEM_NAME);
			$transaction->commit();
		} catch (Exception $e) {
			$transaction->rollback();
		}

		// Send referrer an email
		$mailer = new Mailer();
		$mailer->Subject = 'Your referee ' . $user->getDisplayName() . ' has purchased credits in PropSage';
		$mailer->From = Yii::app()->params["notificationsEmail"];
		$mailer->FromName = Yii::app()->params["notificationsName"];
		$mailer->AddAddress($referrer->email, $referrer->name);

		$tokens = array(
			'referralBonus' => '$' . number_format($referralBonus, 2),
			'referrerName' => $referrer->name,
			'refereeName' => ucwords($user->getDisplayName()),
			'referLink' => $this->createAbsoluteUrl('/refer/index')
		);

		$mailer->createHTMLMail(Yii::getPathOfAlias('common') . "/templates/emails/account/html/acctReferralPurchaseSuccessful.tpl", $tokens);
		$mailer->createTEXTMail(Yii::getPathOfAlias('common') . "/templates/emails/account/text/acctReferralPurchaseSuccessful.tpl", $tokens);

		$mailer->sendMail();
	}

	public function logProblemPayment($problemType, $invoiceNumber)
	{
		// find invoice
		$psInvoice = PsInvoice::model()->findByAttributes(array('invoice_number' => $invoiceNumber));

		$psProblemPayment = new PsProblemPayment();
		$psProblemPayment->invoice_number = $invoiceNumber;
		$psProblemPayment->problem_type = $problemType;
		$psProblemPayment->transaction_details = serialize($_POST);
		$psProblemPayment->date_time = date("Y-m-d H:i:s");
		$psProblemPayment->ip = $_SERVER["REMOTE_ADDR"];

		if ($psInvoice != null) {
			$psProblemPayment->ps_invoice_id = $psInvoice->id;
		}

		return $psProblemPayment->save();
	}

}

?>
